// Copyright 2010, Shuo Chen.  All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.

// Author: Shuo Chen (chenshuo at chenshuo dot com)
//
// This is an internal header file, you should not include this.

#ifndef MUDUO_NET_TIMERQUEUE_H
#define MUDUO_NET_TIMERQUEUE_H

#include <set>
#include <vector>

#include "muduo/base/Mutex.h"
#include "muduo/base/Timestamp.h"
#include "muduo/net/Callbacks.h"
#include "muduo/net/Channel.h"

namespace muduo {
namespace net {

class EventLoop;
class Timer;
class TimerId;

///
/// A best efforts timer queue.
/// No guarantee that the callback will be on time.
///
class TimerQueue : noncopyable
{
public:
    explicit TimerQueue(EventLoop* loop);
    ~TimerQueue();

    ///
    /// 调度回调在给定时间运行
    /// 重复如果@c interval > 0.0。
    ///
    /// 必须是线程安全的通常从其他线程调用。
    TimerId addTimer(TimerCallback cb, Timestamp when, double interval);

    void cancel(TimerId timerId);

private:
    // FIXME: use unique_ptr<Timer> instead of raw pointers.
    // This requires heterogeneous comparison lookup (N3465) from C++14
    // so that we can find an T* in a set<unique_ptr<T>>.
    typedef std::pair<Timestamp, Timer*> Entry;
    typedef std::set<Entry>              TimerList;  // 按到期时间排序
    typedef std::pair<Timer*, int64_t>   ActiveTimer;
    typedef std::set<ActiveTimer>        ActiveTimerSet;  // 按地址大小排序

    // 以下函数只可能在其所属的I/O线程中调用，因此不用加锁
    // 服务器性能杀手之一是锁竞争，因此要尽可能避免用锁
    void addTimerInLoop(Timer* timer);
    void cancelInLoop(TimerId timerId);

    // 当timerfd报警时调用
    void handleRead();

    // move out all expired timers
    // 返回超时的定时器列表
    std::vector<Entry> getExpired(Timestamp now);
    void               reset(const std::vector<Entry>& expired, Timestamp now);

    bool insert(Timer* timer);

    EventLoop* loop_;
    const int  timerfd_;
    Channel    timerfdChannel_;
    // Timer list sorted by expiration
    TimerList timers_;  // 按照到期时间排序

    // for cancel()
    ActiveTimerSet activeTimers_;
    bool           callingExpiredTimers_; /* atomic */  // 是否处于处理超时的定时器中
    ActiveTimerSet cancelingTimers_;
};

}  // namespace net
}  // namespace muduo
#endif  // MUDUO_NET_TIMERQUEUE_H
